/**************************************************
|	File:		CAnimationSystem.cpp
|	Author:		Jake Elmi
|	Course:		SGP Mari's Flower
|	Purpose:	This class is in charge of loading a
|			    a sprite sheet and rendering it
|				to the screen and updating
**************************************************/
#include "AnimationSystem.h"
#include "Animation.h"
#include "../Animation System/AnimTimeStamp.h"

#include "Frames.h"

#include "../../SGD Wrappers/CSGD_TextureManager.h"
#include "../../SGD Wrappers/SGD_String.h"
#include "../TinyXML/tinyxml.h"

#define TM CSGD_TextureManager::GetInstance()

CAnimationSystem* CAnimationSystem::GetInstance( void )
{
	static CAnimationSystem* s_Instance;
	return s_Instance;
}

struct tAnimation
{
	const char*  nID;
	int  nFrames;
	int nLooping;
	vector <CFrames* > vFrame;
};

struct tFrame
{
	int   nAnchorPointX;
	int   nAnchorPointY;
	int   nRenderRectX;
	int   nRenderRectY;
	int   nRenderRectWidth;
	int   nRenderRectHeight;
	int   nActiveRectX;
	int   nActiveRectY;
	int   nActiveRectWidth;
	int   nActiveRectHeight;
	int   nPassiveRectX;
	int   nPassiveRectY;
	int   nPassiveRectWidth;
	int   nPassiveRectHeight;
	int   nDuration;
	char  sEvent [32];
	POINT anchor;

};

CAnimationSystem::CAnimationSystem(void)
{
	m_fTimeWaited = 0.0f;
	m_fSpeed = 1.0f;
	pAnimation = CAnimation::GetInstance();
	
	m_rTemp.left = 0;
	m_rTemp.top = 0;
	m_rTemp.right = 0;
	m_rTemp.bottom = 0;

}

CAnimationSystem::~CAnimationSystem(void)
{
	for ( unsigned int i = 0; i < vAnimation.size(); ++i )
	{
		delete vAnimation[i];
		vAnimation[i] = nullptr;
	}
}


void CAnimationSystem::LoadedAnimation()
{
	
}

void CAnimationSystem::Render(CAnimTimeStamp* TS, int x, int y, bool bFlipped, float fScale, DWORD dwColor)
{
	CAnimation* pAnimation = CAnimation::GetInstance();
	
	// Set RenderRect
	RECT rFrame = {};
	rFrame.left = (LONG)pAnimation->GetListOfFrames()[TS->GetCurrFrame()]->GetRenderRectX();
	rFrame.top  = (LONG)pAnimation->GetListOfFrames()[TS->GetCurrFrame()]->GetRenderRectY();
	rFrame.bottom = (LONG)pAnimation->GetListOfFrames()[TS->GetCurrFrame()]->GetRenderRectHeight();
	rFrame.right  =(LONG) pAnimation->GetListOfFrames()[TS->GetCurrFrame()]->GetRenderRectWidth(); 
	
	// Set AnchorPt.
	POINT ptAnchor = pAnimation->GetListOfFrames()[TS->nCurrFrame]->GetAnchorPt();

	// Flip the image
	float fScale2 = fScale;
	if( bFlipped == true )
		fScale2 = -fScale;

	// Show the image
	CSGD_TextureManager::GetInstance()->Draw(pAnimation->GetImageID(),
		(int)(x-(ptAnchor.x * fScale2)),(int)(y-(ptAnchor.y * fScale)),
		fScale2,fScale,&rFrame,0.0f,0.0f,0.0f,dwColor);

	m_rTemp = rFrame;
}

void CAnimationSystem::Update(CAnimTimeStamp* TS, float dt)
{

	CAnimation* pAnimation = CAnimation::GetInstance();

	// check if paused
	if( pAnimation->GetIsPlaying() == false )
		return;

	// start timer
	m_fTimeWaited += dt * m_fSpeed;

	// iterate to next frame
	if( m_fTimeWaited >= pAnimation->GetListOfFrames()[TS->GetCurrFrame()]->GetDuration())
	{
		m_fTimeWaited = 0.0f;
		++TS->nCurrFrame;

		if(TS->GetCurrFrame() == pAnimation->GetListOfFrames().size() )
		{
			// begin animation again
			if(pAnimation->GetIsLooping() == true )
				TS->nCurrFrame = 0;
			else
			{
				// stop animation
				pAnimation->SetIsPlaying(false);
				--TS->nCurrFrame;
			}
		}
	}
}

bool CAnimationSystem::LoadAnimation( const char* fileName )
{
	TiXmlDocument tDoc;
	if(tDoc.LoadFile( fileName ) == false )
		return false;

	TiXmlElement* pRoot = tDoc.RootElement();
	if( pRoot == nullptr )
		return false;

	Anim = new CAnimation();

	TiXmlElement* pAnimation = pRoot->FirstChildElement( "Animation" );
	TiXmlElement* pFrame = pAnimation->FirstChildElement( "Frame" );

	 while ( pAnimation != nullptr )
	 {	
		 CAnimation* myAnimation = CAnimation::GetInstance();
		 tAnimation Anifo ;
		 pAnimation->Attribute( "numFrames",&Anifo.nFrames );
		 pAnimation->Attribute( "isLooping",&Anifo.nLooping);
		
		 const char * temp = pAnimation->Attribute("ID");
		 if( temp != NULL)
		 {
			 wchar_t* temp2 = new wchar_t[strlen(temp) +1 ];
			 CSTR_TO_TSTR( temp2, ((strlen(temp) + 1) * 2 ),temp);
			 myAnimation->SetImageID(TM->LoadTexture(temp2));
			 delete [] temp2;

		 }
		 
		 
		 
		 myAnimation->SetNumFrames(Anifo.nFrames);
		 if(Anifo.nLooping == 1)
		    myAnimation->SetIsLooping( true );
		 else 
			myAnimation->SetIsLooping( false);

		 while (pFrame != nullptr )
		 {
			 tFrame Framfo = {};
			 CFrames* myFrame = new CFrames();
			 pFrame->Attribute("AnchorPointX", &Framfo.nAnchorPointX);
			 pFrame->Attribute("AnchorPointY", &Framfo.nAnchorPointY);
			 pFrame->Attribute("Duration",&Framfo.nDuration);
			 pFrame->Attribute("RenderRectx", &Framfo.nRenderRectX);
			 pFrame->Attribute("RenderRecty", &Framfo.nRenderRectY);
			 pFrame->Attribute("RenderRectwidth", &Framfo.nRenderRectWidth);
			 pFrame->Attribute("RenderRectheight",&Framfo.nRenderRectHeight);
			 pFrame->Attribute("ActiveRectx", &Framfo.nActiveRectX);
			 pFrame->Attribute("ActiveRecty", &Framfo.nActiveRectY);
			 pFrame->Attribute("ActiveRectwidth",&Framfo.nActiveRectWidth);
			 pFrame->Attribute("ActiveRectheight", &Framfo.nActiveRectHeight);
			 pFrame->Attribute("PassiveRectx", &Framfo.nPassiveRectX);
			 pFrame->Attribute("PassiveRecty", &Framfo.nPassiveRectY);
			 pFrame->Attribute("PassiveRectwidth",&Framfo.nPassiveRectWidth);
			 pFrame->Attribute("PassiveRectheight", &Framfo.nPassiveRectHeight);

			 Framfo.anchor.x = Framfo.nAnchorPointX;
			 Framfo.anchor.y = Framfo.nAnchorPointY;

			 myFrame->SetAchorPt(Framfo.anchor);
			
			 myFrame->SetDuration((float)Framfo.nDuration / 7);
			 myFrame->SetRenderRectX((float)Framfo.nRenderRectX);
			 myFrame->SetRenderRectY((float)Framfo.nRenderRectY);
			 myFrame->SetRenderRectWidth((float)Framfo.nRenderRectWidth);
			 myFrame->SetRenderRectHeight((float)Framfo.nRenderRectHeight);

			 myFrame->SetActiveRectX((float)Framfo.nActiveRectX);
			 myFrame->SetActiveRectY((float)Framfo.nActiveRectY);
			 myFrame->SetActiveRectWidth((float)Framfo.nActiveRectWidth);
			 myFrame->SetActiveRectHeight((float)Framfo.nActiveRectHeight);

			 myFrame->SetPassiveRectX((float)Framfo.nPassiveRectX);
			 myFrame->SetPassiveRectY((float)Framfo.nPassiveRectY);
			 myFrame->SetPassiveRectWidth((float)Framfo.nPassiveRectWidth);
			 myFrame->SetPassiveRectHeight((float)Framfo.nPassiveRectHeight);

		     myAnimation->SetListofFrames(myFrame);
			 pFrame = pFrame->NextSiblingElement( "Frame" );
			
		 }

		 SetListOfAnimations(Anim);
		 pAnimation = pAnimation->NextSiblingElement( "Animation" );

	 }

	return (GetListOfAnimations().size() > 0 );
}